package com.cskaoyan.javase.oop3._2inner._4local._3notice;

/**
 * 局部内部类对象可以作为方法的返回值,返回给外界使用
 * 这时如果局部内部类继承了某个类/接口,就可以使用父类引用指向子类对象
 * 这时仍然可以使用父类引用,操作这个局部内部类对象.
 *
 * 注意事项:
 * 在作用域内部定义的局部内部类当中,如果访问了作用域内部的局部变量
 * 那么这个局部变量应该是一个常量,它只允许访问,不允许修改
 * 在Java8之前,如果在局部内部类中访问作用域内部的局部变量,那么这个局部变量必须直接用final修饰
 * 但是Java8以后,底层做了优化,会自己加final,程序员不需要加了
 *
 * 为什么有这样的设计呢?为什么要把局部变量设定为一个局部常量呢?
 * 之所以这么设计,归根结底是生命周期的冲突问题
 *
 * 由于局部变量随着方法调用完毕销毁
 * 而对象则不会
 * 如果局部内部类对象仍然存在, 并且还要去访问这个"局部变量",那从何处去找到这个局部变量呢?
 *
 * 为了解决这种"对象和局部变量"的生命周期的冲突
 * Java程序会自动将局部内部类当中访问的作用域内部的局部变量,作为自身对象的一个成员变量去存储
 * 也就是说,以后对象访问"局部变量",实际上是访问自身的成员变量
 *
 * 那么以上,究竟和该局部变量成为一个常量有什么关系呢?
 *
 * 这时如果允许局部内部类当中去修改这个"局部变量",那么从代码上看修改的是"作用域内部的局部变量"
 * 但从内存角度实际上修改的是自身对象的成员变量
 * 于是就需要将"自身成员变量的修改"同步到"作用域内部的局部变量"
 * 存在一个同步的过程
 *
 * 这种设计,Java的开发者没有采取,而是直接堵死了,不允许修改,就不存在同步的问题.
 * 我们针对一个问题,一个困难,提出了一个解决的思路/方案
 *      也许它能够解决以前的问题,但很有可能它本身也是一个问题.
 *
 *
 * @since 14:55
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 父类引用指向局部子类内部类对象
        IA ia = new A().test();
        ia.method();

    }
}

class A {
    public IA test() {
        // 外围类成员方法中定义的局部变量
        int num = 10;
        class Inner implements IA {
            @Override
            public void method() {
                // 成员方法中的局部内部类去访问作用域成员方法中的局部变量
                System.out.println(num);
                // num++;
            }
        }
        // new Inner().method();
        // System.out.println(num);

        return new Inner();
    }
}

interface IA {
    void method();
}